home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-01
/
cuj1008.zip
/
1008083A
< prev
next >
Wrap
Text File
|
1991-12-04
|
6KB
|
173 lines
// refptr.hpp - Macros for RefCntPtrs
// These macros simplify the process of
// creating a new reference count pointer
// class for a new class type - instead of
// copying an existing one and changing the
// names with a text editor, the
// preprocessor is used to substitute the
// appropriate names. This is basically an
// attempt to emulate class templates, until
// C++ compilers that implement templates
// are available.
//
// There are two primary macros here - the
// first is the DECLARE macro, for the class
// declaration and inline functions, i.e.
// the stuff usually found in the ".hpp"
// file. The DEFINE macro contains the
// definition of the non-inline member
// functions - the stuff usually found in
// the ".cpp" file.
//
// To use these, simply create a class
// derived from RefCntItem, then put a
// RefCntPtrDECLARE() in an appropriate
// header file and a RefCntPtrDEFINE() in
// appropriate definition file (the class
// name is substituted for 'type').
#ifndef RefCntPtr_MACROS
#define RefCntPtr_MACROS
// this is used to create a name for
// the class being defined, by
// concatenating the original item
// class name with "RefCntPtr"
#define RefCntPtr(type) \
type ## RefCntPtr
// If DEBUG is defined, using a zero
// pointer (an error) results in a
// message. An exit() statement
// might also be appropriate.
#ifdef DEBUG
#include <iostream.h>
#define RefCntPtrDebug(type) \
if (0 == p_ptr) \
cout << "ERROR - using 0 " \
"RefCntPtr to " #type "\n";
#else
#define RefCntPtrDebug(type)
#endif
#define RefCntPtrDECLARE(type) \
class RefCntPtr(type) \
{ \
private: \
\
type * p_ptr; \
\
void p_inc (void); \
\
void p_decAndDelete ( \
type * dest); \
\
void p_assign ( \
type * rVal); \
public: \
RefCntPtr(type) (void) \
: p_ptr(0) {;}; \
\
RefCntPtr(type) ( \
const RefCntPtr(type)& in) \
: p_ptr (in.p_ptr) \
{ p_inc(); }; \
\
RefCntPtr(type) ( \
type * in) \
: p_ptr(in) \
{ p_inc(); }; \
\
~RefCntPtr(type) (void) \
{p_decAndDelete(p_ptr);}; \
\
RefCntPtr(type) & operator = ( \
RefCntPtr(type) & rVal) \
{ p_assign (rVal.p_ptr); \
return *this; }; \
\
RefCntPtr(type) & operator = ( \
type * rVal) \
{ p_assign (rVal); \
return *this; }; \
\
type * operator -> (void) \
{ RefCntPtrDebug(type) \
return p_ptr; }; \
\
type & operator * (void) \
{ RefCntPtrDebug(type) \
return *p_ptr; }; \
\
/* see note */ \
operator int (void) \
{return (p_ptr != 0);}; \
\
private: \
int operator == (RefCntPtr(type)&); \
int operator != (RefCntPtr(type)&); \
int operator < (RefCntPtr(type)&); \
int operator <= (RefCntPtr(type)&); \
int operator > (RefCntPtr(type)&); \
int operator >= (RefCntPtr(type)&); \
};
// operator int() allows comparisons such as
// if (ptr) {},
// which is great. Unfortunately, it also
// allows comparisons such as
// if (ptr1 == ptr2) {}
// to compile, but not as expected
// - operator int() is first applied to
// both sides, then the comparison is made
// with the resulting integers.
//
// This behavior can be overridden by
// declaring operator== - it has precedence
// here. Since I am working in MS-DOS with
// its segmented addressing, I didn't want
// pointer comparisons, (they don't always
// work) so I made operator== and its
// companions private. It would be simple
// to make them public and implement them
// if needed.
#define RefCntPtrDEFINE(type) \
void RefCntPtr(type)::p_assign( \
type * rVal) \
\
/* the order of the calls to the */ \
/* increment and decrement functions */ \
/* is significant here. If the rVal */ \
/* and current value point to the same */ \
/* place, we could delete the item and */ \
/* then discover we need it. */ \
{ \
type * tmp = p_ptr; \
p_ptr = rVal; \
p_inc(); \
p_decAndDelete(tmp); \
}; \
\
void RefCntPtr(type)::p_inc (void) \
{ \
if (p_ptr) \
p_ptr->incRefCnt(); \
}; \
\
void RefCntPtr(type)::p_decAndDelete ( \
type * dest) \
{ \
if (dest) \
{ \
dest->decRefCnt(); \
if (0 == dest->refCnt()) \
delete dest; \
}; \
};
#endif